//
// Copyright 2010 Marcel Urbanek
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//      http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package de.urbiworx.typewriter;

import java.util.List;
import java.util.Map;

import org.w3c.css.sac.LexicalUnit;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * @author Marcel
 *
 */
public class CSSApplyer {
	
	Document document;
	List<ComplexSelector> selectors;
	boolean merged=false;
	
	public Document getMergedDocument(){
		if (!merged){
			throw new RuntimeException("use merge() first, document is unmerged");
		}
		return document;
	}
	CSSApplyer(Document document,List<ComplexSelector> selectors){
		this.document=document;
		this.selectors=selectors;
	}
	
	public void merge(){
		Element element=(Element) document.getChildNodes().item(0);
		merge(element);
		merged=true;
		
	}
	
	/**
	 * Applies all CSS Styles to the given element and all its children
	 * @param mergeElement
	 */
	private void merge(Element mergeElement){
		//Using Wrapper that extends CSSStyleableElement to allow access to id and class
		//Attributes
		ElementWrapper wrappedElement=new ElementWrapper(mergeElement);
		//Doing cinderella (looking for selectors that fit)
		for (int i=0;i<selectors.size();i++){
			if(selectors.get(i).getSelector().match(wrappedElement, "")){
				for (Map.Entry<String, LexicalUnit> entry:selectors.get(i).getProperties().entrySet()){
					String value;
					LexicalUnit unit=entry.getValue(); 
					//Check if current style attribute is a string one
					if (unit.getLexicalUnitType()==LexicalUnit.SAC_URI||
							unit.getLexicalUnitType()==LexicalUnit.SAC_ATTR||
							unit.getLexicalUnitType()==LexicalUnit.SAC_IDENT||
							unit.getLexicalUnitType()==LexicalUnit.SAC_STRING_VALUE){
						value=unit.getStringValue();
					} else {
						//its an actual value
						value=unit.getFloatValue()+"";
						if (unit.getDimensionUnitText()!=null){
							value+=unit.getDimensionUnitText();
						}
					}
					mergeElement.setAttribute(entry.getKey(), value);
				}
			}
		}
		//tidy up:fop doesn't know the class attribute
		mergeElement.removeAttribute("class");
		NodeList list=mergeElement.getChildNodes();
		for (int i=0;i<list.getLength();i++){
			if (list.item(i) instanceof Element){
				merge((Element) list.item(i));
			}
		}
	}
}
